package rm.ep.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import rm.ep.shared.BlobEntity;
import rm.ep.shared.LogEntity;
import rm.ep.shared.EnquiryEntity;
import rm.ep.shared.FileEntity;
import rm.ep.shared.KeywordEntity;
import rm.ep.shared.ProgressEntity;
import rm.ep.shared.SubscriberEntity;

import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.util.DAOBase;

public class BaseDAO extends DAOBase {

	static {
		ObjectifyService.register(KeywordEntity.class);
		ObjectifyService.register(BlobEntity.class);
		ObjectifyService.register(FileEntity.class);
		ObjectifyService.register(LogEntity.class);
		ObjectifyService.register(ProgressEntity.class);
		ObjectifyService.register(SubscriberEntity.class);
		ObjectifyService.register(EnquiryEntity.class);
//		ObjectifyService.register(CommentEntity.class);
	}
		
	static {
		Properties properties = new Properties();
		InputStream is = null;
		try {
			is = ClassLoader.getSystemResourceAsStream("rm/ep/server/BaseDAO.properties");
		    properties.load(is);
		    is.close();
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
		EMAIL_HEADER = properties.getProperty("email.header");
		EMAIL_FOOTER = properties.getProperty("email.footer");
		EMAIL_ADDRESS_NOREPLY = properties.getProperty("email.address.noreply");
		EMAIL_ADDRESS_DEFAULT = properties.getProperty("email.address.default");
		EMAIL_SUBJECT_PREFIX = properties.getProperty("email.subject.prefix");
		properties.clear();
	}

	protected static interface Transactable {
		void execute(Objectify ofy);
	}
	
	protected final static void transact(Transactable t) {
		Objectify ofy = ObjectifyService.beginTransaction();
		try {
			t.execute(ofy);
			ofy.getTxn().commit();
		} finally {
			if (ofy.getTxn().isActive()) {
				ofy.getTxn().rollback();
			}
		}		
	}
	
	protected static <T> List<T> getChildren(com.google.appengine.api.datastore.Key parent, Class<T> clazz) {
		return getChildren(Key.typed(parent), clazz);
	}
	
	protected static <T> List<T> getChildren(Object parent, Class<T> clazz) {
		return ObjectifyService.begin().query(clazz).ancestor(parent).order("fCreatedAt").list();
	}

	protected final static boolean sendEmail(String toEmail, String fromEmail, 
			String subject, String body) {
		try {
			InternetAddress from = new InternetAddress(fromEmail);
			InternetAddress to = new InternetAddress(toEmail);
			return sendEmail(from, to, subject, body);
	    } catch (AddressException e) {
	    	return false;
		}		
	}
	
	protected final static boolean sendEmail(String toEmail, String toName, 
			String fromEmail, String fromName, String subject, String body) {
		try {
			InternetAddress from = new InternetAddress(fromEmail, fromName);
			InternetAddress to = new InternetAddress(toEmail, fromName);
			return sendEmail(from, to, subject, body);
	    } catch (UnsupportedEncodingException e) {
	    	return false;
		}		
	}
	
	protected final static boolean sendEmail(InternetAddress from, 
			InternetAddress to, String subject, String body) {
		Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        try {
            Message msg = new MimeMessage(session);
            msg.setFrom(from);
            msg.addRecipient(Message.RecipientType.TO, to);
            msg.setSubject(subject);
            msg.setText(body);
            Transport.send(msg);
            return true;
        } catch (MessagingException e) {
            return false;
        }
	}

	protected final static String formatDate(Long time) {
		return DATE_FORMAT.format(new Date(time));
	}
	
	protected final static String getOperator(String defValue) {
		if (USER_SVC.getCurrentUser() == null) {
			return defValue;
		}
		return USER_SVC.getCurrentUser().getEmail();
	}
	
	protected final static String join(String prefix, List<String> strings) {
		StringBuilder builder = new StringBuilder(prefix);
		for (String s : strings) {
			builder.append(s).append(" ");
		}
		return builder.toString();
	}
	
	protected static String EMAIL_HEADER, EMAIL_FOOTER, 
							EMAIL_ADDRESS_NOREPLY, EMAIL_ADDRESS_DEFAULT,
							EMAIL_SUBJECT_PREFIX;
	
	private final static UserService USER_SVC = UserServiceFactory.getUserService();
	
	private final static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MMM-dd HH:mm");  

}
